package org.pentaho.cubic.client.commands.model;

import org.pentaho.cubic.client.dialogs.LoginDialog;
//import org.pentaho.cubic.client.dialogs.NotificationDialog;
import org.pentaho.cubic.client.service.CubicServiceCache;

//import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.rpc.AsyncCallback;

/**
 * This abstract class needs to be extend when using any command that
 * requires server authentication. The execute method first check whether the user is authenticated
 * or not and then if the user is authentication is performs the command described in the 
 * performOperation method, otherwise the login screen will be displayed back to the user
 *
 */

public abstract class CubicCommand implements Command {

	private ICommandCallback commandCallback;

	/**
	 * Checks if the user is logged in, if the user is then it perform operation other
	 * wise user if ask to perform the login operation again
	 * @param feedback  if the feedback needs to be sent back to the caller. Not used currently
	 */
	public void execute(final boolean feedback) {
		final AsyncCallback<Boolean> callback = new AsyncCallback<Boolean>() {
			public void onSuccess(Boolean result) {
				performOperation(feedback);	
			}

			public void onFailure(Throwable caught) {
				doLogin(feedback);
			}
		};
		CubicServiceCache.getService().isAuthenticated(callback);

	}


	/**
	 * Checks if the user is logged in, if the user is then it perform operation other
	 * wise user if ask to perform the login operation again.
	 * <p>
	 * After the operation is executed, the CommandCallback object receives an afterExecute() 
	 * notification. 
	 * 
	 * @param commandCallback CommandCallback object to receive execution notification.
	 */
	public void execute(ICommandCallback commandCallback){
		execute(commandCallback, false);
	}

	/**
	 * Checks if the user is logged in, if the user is then it perform operation other
	 * wise user if ask to perform the login operation again.
	 * <p>
	 * After the operation is executed, the CommandCallback object receives an afterExecute() 
	 * notification. 
	 * 
	 * @param commandCallback CommandCallback object to receive execution notification.
	 * @param feedback  if the feedback needs to be sent back to the caller. Not used currently
	 */
	public void execute(final ICommandCallback commandCallback, final boolean feedback){
		this.commandCallback = commandCallback;

		final AsyncCallback<Boolean> callback = new AsyncCallback<Boolean>() {
			public void onSuccess(Boolean result) {
				performOperation(feedback); 
				commandCallback.afterExecute();
			}

			public void onFailure(Throwable caught) {
				doLogin(feedback);
			}
		};
		CubicServiceCache.getService().isAuthenticated(callback);
	}

	/**
	 * Checks if the user is logged in, if the user is then it perform operation other
	 * wise user if ask to perform the login operation again
	 */
	public void execute() {
		final AsyncCallback<Boolean> callback = new AsyncCallback<Boolean>() {
			public void onSuccess(Boolean result) {
				performOperation();	
			}

			public void onFailure(Throwable caught) {
				doLogin();
			}
		};
		CubicServiceCache.getService().isAuthenticated(callback);

	}

	/**
	 * Display the login screen and and validate the credentials supplied by the user
	 * if the credentials are correct, the execute method is being invoked other wise
	 * error dialog is being display. On clicking ok button on the dialog box, login
	 * screen is displayed again and process is repeated until the user click cancel 
	 * or user is successfully authenticated
	 * @param feedback  if the feedback needs to be sent back to the caller. Not used currently
	 */
	private void doLogin(final boolean feedback) {
		LoginDialog.performLogin(new AsyncCallback<Object>() {

			public void onFailure(Throwable caught) {
				//NotificationDialog dialogBox = new NotificationDialog("Error","Invalid Login"); //$NON-NLS-1$ //$NON-NLS-2$
				//dialogBox.center();
			}

			public void onSuccess(Object result) {
				if(commandCallback != null){
					execute(commandCallback, feedback);
				} else {
					execute(feedback);
				}
			}

		});
	}

	/**
	 * Display the login screen and and validate the credentials supplied by the user
	 * if the credentials are correct, the execute method is being invoked other wise
	 * error dialog is being display. On clicking ok button on the dialog box, login
	 * screen is displayed again and process is repeated until the user click cancel 
	 * or user is successfully authenticated
	 *  */
	private void doLogin() {
		LoginDialog.performLogin(new AsyncCallback<Object>() {
			
			public void onFailure(Throwable caught) {
				//NotificationDialog dialogBox = new NotificationDialog("Error","Invalid Login"); //$NON-NLS-1$ //$NON-NLS-2$
				//dialogBox.center();
			}

			public void onSuccess(Object result) {
				if(commandCallback != null){
					execute(commandCallback);
				} else {
					execute();
				}
			}

		});
	}


	/**
	 * This is an abstract method which the extending class with implement with logic of performing
	 * specific operation
	 *
	 *  */
	protected abstract void performOperation();
	/**
	 * This is an abstract method which the extending class with implement with logic of performing
	 * specific operation
	 * @param feedback  if the feedback needs to be sent back to the caller. Not used currently
	 * 
	 *  */
	protected abstract void performOperation(final boolean feedback);

}
